package gui;

import gui.secondary.BackgroundSecondaryMenu;
import gui.secondary.MapLayerSecondaryMenu;
import gui.secondary.MapObjectSecondaryMenu;
import gui.secondary.MapSecondaryMenu;
import gui.secondary.StrataSecondaryMenu;

import java.awt.GridBagLayout;
import java.awt.GridBagConstraints;
import java.awt.MenuBar;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;

import controller.gui.DefaultCancelButtonController;
import controller.gui.InsertionDisplayController;
import controller.gui.SelectionBoxController;
import controller.gui.backgroundmenu.BackgroundConceptBrowseController;
import controller.gui.backgroundmenu.BackgroundConceptSelectionBoxController;
import controller.gui.backgroundmenu.BackgroundOKButtonController;
import controller.gui.backgroundmenu.BackgroundRendererBrowseController;
import controller.gui.backgroundmenu.BackgroundRendererSelectionBoxController;
import controller.gui.informationpanel.MapInformationController;
import controller.gui.mainmenu.BackgroundWizardController;
import controller.gui.mainmenu.DeleteMapElementController;
import controller.gui.mainmenu.DownCurrentStrataWizardController;
import controller.gui.mainmenu.MapLayerWizardController;
import controller.gui.mainmenu.MapObjectWizardController;
import controller.gui.mainmenu.MapPropertiesWizardController;
import controller.gui.mainmenu.MapStrataWizardController;
import controller.gui.mainmenu.UpCurrentStrataWizardController;
import controller.gui.maplayermenu.MapLayerConceptBrowseController;
import controller.gui.maplayermenu.MapLayerOKController;
import controller.gui.maplayermenu.MapLayerRendererBrowseController;
import controller.gui.mapmenu.MapPropertiesOKController;
import controller.gui.mapobjectmenu.MapObjectConceptBrowseController;
import controller.gui.mapobjectmenu.MapObjectConceptSelectionBoxController;
import controller.gui.mapobjectmenu.MapObjectOKButtonController;
import controller.gui.mapobjectmenu.MapObjectRendererBrowseController;
import controller.gui.mapobjectmenu.MapObjectRendererSelectionBoxController;
import controller.gui.mapstratamenu.MapStrataAddAfterCurrentController;
import controller.gui.mapstratamenu.MapStrataAddCeilingController;
import controller.gui.mapstratamenu.MapStrataAddFloorController;
import controller.gui.mapstratamenu.MapStrataCancelButtonController;
import controller.gui.mapstratamenu.MapStrataDeleteCurrentController;
import controller.gui.menubar.ExitMapController;
import controller.gui.menubar.NewMapController;
import controller.gui.menubar.OpenMapController;
import controller.gui.menubar.SaveMapAsController;
import controller.gui.menubar.SaveMapController;

/** La classe MapEditorFrame si preoccupa di definire l'aspetto grafico
 *  complessivo dell'Editor, distribuendo i vari componenti secondo un
 *  ben preciso layout.
 * @author Daniele
 * @version 2.7 */
public class MapEditorFrame extends JFrame{

	private static final long serialVersionUID = -1403271070433484198L;
	
	/** E' la barra dei Menu che compare appena sotto al titolo della finestra. */
	private MapEditorMenuBar topMenu;
	/** Il layout utilizzato per disporre i tre componenti principali. */
	private GridBagLayout layout;
	/** I constraints associati al GridBagLayout. */
	private GridBagConstraints constraints;
	/** Il menu di navigazione primario collocato sul lato sinistro dello schermo. */
	private PrimaryMenu primaryMenu;
	/** La porzione centrale dell'Editor. */
	private CentralView centralView;
	/** Il menu secondario in versione mappa. */
	private MapSecondaryMenu mapSecondaryMenu;
	/** Il menu secondario in versione sfondo. */
	private BackgroundSecondaryMenu backgroundSecondaryMenu;
	/** Il menu secondario in versione mapLayer. */
	private MapLayerSecondaryMenu mapLayerSecondaryMenu;
	/** Il menu secondario in versione mapObject. */
	private MapObjectSecondaryMenu mapObjectSecondaryMenu;
	/** Il menu secondario in versione strata. */
	private StrataSecondaryMenu strataSecondaryMenu;
	/** Una riga di testo sul bordo inferiore della finestra per l'output di informazioni. */
	private JTextField log;
	
	
	public MapEditorFrame(String _title,NewMapController newmap,OpenMapController openmap,SaveMapController save,SaveMapAsController saveas,ExitMapController exit,MapInformationController mapinfo,MapPropertiesOKController mappropok,DefaultCancelButtonController mappropcancel){
		this(_title);
		//TODO in un futuro serve un metodo chiaro dove i componenti grafici vengono cablati... non come ora che che sono alla belle e meglio nel costruttore
	}
	/**
	 * 
	 * @return il display contenuto nella CentralView
	 */
	public Display getDisplay(){
		return this.getCentralView().getDisplay();
	}
	
	
	/**aggiunge i Controller alla grafica, permettendo il <strong>cablaggio</strong> tra grafica e Controller. in questo modo
	 * gli eventi generati dai componenti grafici possono essere opportunamente gestiti dai specifici Controller 
	 * 
	 * @param newmap indica il controller che deve gestire il pulsante di creazione nuova mappa
	 * @param openmap indica il controller che deve gestire il pulsante di aperturna vecchia mappa
	 * @param save indica il controller che deve gestire il pulsante di salvataggio veloce della mappa
	 * @param saveas indica il controller che deve gestire il pulsante di salvataggio della mappa
	 * @param exit indica il controller che deve gestire la richiesta di uscita dal programma
	 * @param mapinfo indica il controller che deve gestire le attuali coordinate del mouse sul Display
	 * @param mappropok indica il controller che deve gestire il pulsante di conferma nel sottomenu Map
	 * @param mappropcancel indica il controller che deve gestire il pusaltendi annulla nel sootmenu Map
	 */
//	public void addListeners(
//			NewMapController newmap,OpenMapController openmap,SaveMapController save,SaveMapAsController saveas,ExitMapController exit,
//			MapInformationController mapinfo,DisplayController displaycontroller,
//			MapPropertiesWizardController editmap,MapPropertiesOKController mappropok,DefaultCancelButtonController mappropcancel,
//			BackgroundWizardController bkg,BackgroundOKButtonController bkgok,DefaultCancelButtonController bkgcancel,BackgroundConceptBrowseController bkgconceptbrowse,BackgroundRendererBrowseController bkgrendererbrowse,BackgroundConceptSelectionBoxController bkgconceptbox,BackgroundRendererSelectionBoxController bkgrendererbox,
//			MapLayerWizardController ml,MapLayerOKController mlok,DefaultCancelButtonController mlcancel,MapLayerConceptBrowseController mlconceptbrowse,MapLayerRendererBrowseController mlrendererbrowse,SelectionBoxController mlconceptbox,SelectionBoxController mlrendererbox,
//			MapObjectWizardController mo,MapObjectOKButtonController mook,DefaultCancelButtonController mocancel,MapObjectConceptBrowseController moconceptbrowse,MapObjectRendererBrowseController morendererbrowse,MapObjectConceptSelectionBoxController moconceptbox,MapObjectRendererSelectionBoxController morendererbox,
//			MapStrataWizardController sw,MapStrataCancelButtonController mscancel,MapStrataAddAfterCurrentController msaddcurrent,MapStrataAddFloorController msaddfloor,MapStrataAddCeilingController msaddceiling,MapStrataDeleteCurrentController msdelete,
//			DownCurrentStrataWizardController downstratum,
//			UpCurrentStrataWizardController upstratum,
//			DeleteMapElementController delete
//			) throws NullPointerException{
//		
//		//menu listeners
//		this.topMenu.addMenuListener(newmap, openmap, save, saveas, exit);
//		//display listener
//		mapinfo.wire(this.centralView.getDisplay());
//		displaycontroller.wire(this.centralView.getDisplay());
//		//primary menu listeners
//		this.primaryMenu.addListeners(editmap,bkg,ml,mo,sw,downstratum,upstratum,delete);
//		//secondary menu listeners
//		this.mapSecondaryMenu.addListeners(mappropok, mappropcancel);
//		this.backgroundSecondaryMenu.addListeners(bkgok, bkgcancel,bkgconceptbrowse, bkgrendererbrowse, bkgconceptbox, bkgrendererbox);
//		
//		this.mapLayerSecondaryMenu.addListeners(mlok, mlcancel, mlconceptbrowse,mlrendererbrowse, mlconceptbox, mlrendererbox);
//		this.mapObjectSecondaryMenu.addListeners(mook, mocancel, moconceptbrowse, morendererbrowse, moconceptbox, morendererbox);
//		this.strataSecondaryMenu.addListeners(mscancel,msaddcurrent, msaddfloor, msaddceiling, msdelete);
//		//other listeners
//	}
	
	
	/** Costruisce un MapEditorFrame completo di tutti i componenti per rappresentare
	 *  graficamente l'Editor, come da progetto. Richiede unicamente una String che
	 *  definisca il titolo da dare alla finestra dell'Editor.
	 * @param _title  il titolo da dare alla finestra dell'Editor. */
	public MapEditorFrame(String _title){
		
		super(_title);						// usa il costruttore di JFrame che richiede solo una String.
		this.setSize(800, 600);				// stabilisce quali sono le dimensioni in altezza e larghezza del JFrame.
		this.setVisible(true);				// consente di rendere sempre visibile il JFrame.
		this.setFocusable(true);
		topMenu = new MapEditorMenuBar();	// costruisce un nuovo MapEditorMenuBar.
		this.setJMenuBar(this.topMenu);		// associa al JFrame il MapEditorMenuBar appena creato.
		
		layout = new GridBagLayout();
		constraints = new GridBagConstraints();
		this.setLayout(layout);
		
		primaryMenu = new PrimaryMenu();
		this.addMenusToLayout(primaryMenu, 0, 0.5);
		
		centralView = new CentralView();
		this.addMenusToLayout(centralView, 1, 4);
		
		mapSecondaryMenu = new MapSecondaryMenu();
		this.addMenusToLayout(mapSecondaryMenu, 2, 0.5);
		this.mapSecondaryMenu.setVisible(false);
		
		backgroundSecondaryMenu = new BackgroundSecondaryMenu();
		this.addMenusToLayout(backgroundSecondaryMenu, 2, 0.5);
		this.backgroundSecondaryMenu.setVisible(false);
		
		mapLayerSecondaryMenu = new MapLayerSecondaryMenu();
		this.addMenusToLayout(mapLayerSecondaryMenu, 2, 0.5);
		this.mapLayerSecondaryMenu.setVisible(false);
		
		mapObjectSecondaryMenu = new MapObjectSecondaryMenu();
		this.addMenusToLayout(mapObjectSecondaryMenu, 2, 0.5);
		this.mapObjectSecondaryMenu.setVisible(false);
		
		strataSecondaryMenu = new StrataSecondaryMenu();
		this.addMenusToLayout(strataSecondaryMenu, 2, 0.5);
		this.strataSecondaryMenu.setVisible(false);
		
		log = new JTextField();
		log.setEditable(false);
		constraints.gridx = 0;
		constraints.gridy = 1;
		constraints.weightx = 0;
		constraints.weighty = 0.05;
		constraints.insets.top = 5;
		constraints.gridwidth = 3;
		layout.setConstraints(log, constraints);
		this.add(log, constraints);
		
		this.validate();		// rende immediatamente visibile la distribuzione dei componenti.
		this.setDefaultCloseOperation(DISPOSE_ON_CLOSE);//termina il processo dell'editor in caso l'utente preme la X della finestra stessa
	}

	private void addMenusToLayout(JPanel menu, int order, double weightx){
		constraints.gridx = order;
		constraints.gridy = 0;
		constraints.weightx = weightx;
		constraints.weighty = 1;
		constraints.anchor = GridBagConstraints.CENTER;
		constraints.fill = GridBagConstraints.BOTH;
		constraints.insets.top = 10;
		constraints.insets.bottom = 10;
		constraints.insets.left = 10;
		constraints.insets.right = 10;
		layout.setConstraints(menu, constraints);
		this.add(menu, constraints);
	}
	
	/** Getter per il menu a tendina sul bordo superiore dell'Editor.
	 * @return the topMenu. For further information visit {@link #topMenu} */
	public MapEditorMenuBar getTopMenu() {
		return topMenu;
	}

	/** Getter per il PrimaryMenu.
	 * @return the primaryMenu. For further information visit {@link #primaryMenu} */
	public PrimaryMenu getPrimaryMenu() {
		return primaryMenu;
	}

	/** Getter per la CentralView.
	 * @return the centralView. For further information visit {@link #centralView} */
	public CentralView getCentralView() {
		return centralView;
	}

	/** Getter per la versione Map del SecondaryMenu.
	 * @return the mapSecondaryMenu. For further information visit {@link #mapSecondaryMenu} */
	public MapSecondaryMenu getMapSecondaryMenu() {
		return mapSecondaryMenu;
	}

	/** Getter per la versione Background del SecondaryMenu.
	 * @return the backgroundSecondaryMenu. For further information visit {@link #backgroundSecondaryMenu} */
	public BackgroundSecondaryMenu getBackgroundSecondaryMenu() {
		return backgroundSecondaryMenu;
	}

	/** Getter per la versione MapLayer del SecondaryMenu.
	 * @return the mapLayerSecondaryMenu. For further information visit {@link #mapLayerSecondaryMenu} */
	public MapLayerSecondaryMenu getMapLayerSecondaryMenu() {
		return mapLayerSecondaryMenu;
	}
	
	/** Getter per la versione MapObject del SecondaryMenu.
	 * @return the mapObjectSecondaryMenu. For further information visit {@link #mapObjectSecondaryMenu} */
	public MapObjectSecondaryMenu getMapObjectSecondaryMenu(){
		return mapObjectSecondaryMenu;
	}
	/**
	 * @return the strataSecondaryMenu. For further information visit {@link #strataSecondaryMenu}
	 */
	public StrataSecondaryMenu getStrataSecondaryMenu() {
		return strataSecondaryMenu;
	}
	/**
	 * @return the log. For further information visit {@link #log}
	 */
	public JTextField getLog() {
		return log;
	}
	
	public MapEditorMenuBar getJMenuBar(){
		return this.topMenu;
	}
	
	
	
	
}
